home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 2
/
Atari Mega Archive CD - Volume 2.iso
/
minix
/
up1510b.tgz
/
up1510b
/
src
/
fs
/
main.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-07-23
|
17KB
|
564 lines
/* This file contains the main program of the File System. It consists of
* a loop that gets messages requesting work, carries out the work, and sends
* replies.
*
* The entry points into this file are
* main: main program of the File System
* reply: send a reply to a process after the requested work is done
*/
#include "fs.h"
#include <minix/callnr.h>
#include <minix/com.h>
#include <minix/boot.h>
#include "buf.h"
#include "file.h"
#include "fproc.h"
#include "inode.h"
#include "param.h"
#include "super.h"
#if FASTLOAD
#include "dev.h"
#endif
#define M64K 0xFFFF0000L /* 16 bit mask for DMA check */
#define MAX_RAM 16384 /* maximum RAM disk size in blocks */
#define RAM_IMAGE (dev_t)0x303 /* major-minor dev where root image is kept */
#define DEMO_RAM_OFFSET 200 /* location of RAM image on demo diskette */
FORWARD void buf_pool();
FORWARD void fs_init();
FORWARD void get_boot_parameters();
FORWARD void get_work();
FORWARD dev_t load_ram();
FORWARD void load_super();
#if ASKDEV
FORWARD int askdev();
#endif
#if FASTLOAD
FORWARD void fastload();
FORWARD int lastused();
#endif
#if (CHIP == INTEL)
FORWARD phys_bytes get_physbase();
#endif
/*===========================================================================*
* main *
*===========================================================================*/
PUBLIC void main()
{
/* This is the main program of the file system. The main loop consists of
* three major activities: getting new work, processing the work, and sending
* the reply. This loop never terminates as long as the file system runs.
*/
int error;
fs_init();
/* This is the main loop that gets work, processes it, and sends replies. */
while (TRUE) {
get_work(); /* sets who and fs_call */
fp = &fproc[who]; /* pointer to proc table struct */
super_user = (fp->fp_effuid == SU_UID ? TRUE : FALSE); /* su? */
dont_reply = FALSE; /* in other words, do reply is default */
/* Call the internal function that does the work. */
if (fs_call < 0 || fs_call >= NCALLS)
error = EBADCALL;
else
error = (*call_vector[fs_call])();
/* Copy the results back to the user and send reply. */
if (dont_reply) continue;
reply(who, error);
if (rdahed_inode != NIL_INODE) read_ahead(); /* do block read ahead */
}
}
/*===========================================================================*
* get_work *
*===========================================================================*/
PRIVATE void get_work()
{
/* Normally wait for new input. However, if 'reviving' is
* nonzero, a suspended process must be awakened.
*/
register struct fproc *rp;
if (reviving != 0) {
/* Revive a suspended process. */
for (rp = &fproc[0]; rp < &fproc[NR_PROCS]; rp++)
if (rp->fp_revived == REVIVING) {
who = (int)(rp - fproc);
fs_call = rp->fp_fd & BYTE;
fd = (rp->fp_fd >>8) & BYTE;
buffer = rp->fp_buffer;
nbytes = rp->fp_nbytes;
rp->fp_suspended = NOT_SUSPENDED; /*no longer hanging*/
rp->fp_revived = NOT_REVIVING;
reviving--;
return;
}
panic("get_work couldn't revive anyone", NO_NUM);
}
/* Normal case. No one to revive. */
if (receive(ANY, &m) != OK) panic("fs receive error", NO_NUM);
who = m.m_source;
fs_call = m.m_type;
}
/*===========================================================================*
* reply *
*===========================================================================*/
PUBLIC void reply(whom, result)
int whom; /* process to reply to */
int result; /* result of the call (usually OK or error #) */
{
/* Send a reply to a user process. It may fail (if the process has just
* been killed by a signal), so don't check the return code. If the send
* fails, just ignore it.
*/
reply_type = result;
send(whom, &m1);
}
/*===========================================================================*
* fs_init *
*===========================================================================*/
PRIVATE void fs_init()
{
/* Initialize global variables, tables, etc. */
register struct inode *rip;
int i;
dev_t d; /* device to fetch the superblock from */
buf_pool(); /* initialize buffer pool */
get_boot_parameters();
d = load_ram(); /* init RAM disk, load if it is root */
load_super(d); /* Load super block for root device */
/* Initialize the 'fproc' fields for process 0 and process 2. */
for (i = 0; i < 3; i+= 2) {
fp = &fproc[i];
rip = get_inode(ROOT_DEV, ROOT_INODE);
fp->fp_rootdir = rip;
dup_inode(rip);
fp->fp_workdir = rip;
fp->fp_realuid = (uid_t) SYS_UID;
fp->fp_effuid = (uid_t) SYS_UID;
fp->fp_realgid = (gid_t) SYS_GID;
fp->fp_effgid = (gid_t) SYS_GID;
fp->fp_umask = ~0;
}
/* Certain relations must hold for the file system to work at all. */
if (ZONE_NUM_SIZE != 2) panic("ZONE_NUM_SIZE != 2", NO_NUM);
if (SUPER_SIZE > BLOCK_SIZE) panic("SUPER_SIZE > BLOCK_SIZE", NO_NUM);
if(BLOCK_SIZE % INODE_SIZE != 0)panic("BLOCK_SIZE % INODE_SIZE != 0",NO_NUM);
if (OPEN_MAX > 127) panic("OPEN_MAX > 127", NO_NUM);
if (NR_BUFS < 6) panic("NR_BUFS < 6", NO_NUM);
if (sizeof(d_inode) != 32) panic("inode size != 32", NO_NUM);
}
/*===========================================================================*
* buf_pool *
*===========================================================================*/
PRIVATE void buf_pool()
{
/* Initialize the buffer pool. On the IBM PC, the hardware DMA chip is
* not able to cross 64K boundaries, so any buffer that happens to lie
* across such a boundary is not used. This is not very elegant, but all
* the alternative solutions are as bad, if not worse. The fault lies with
* the PC hardware.
*/
register struct buf *bp;
vir_bytes low_off, high_off; /* only used on INTEL chips */
phys_bytes org;
bufs_in_use = 0;
front = &buf[0];
rear = &buf[NR_BUFS - 1];
for (bp = &buf[0]; bp < &buf[NR_BUFS]; bp++) {
bp->b_blocknr = NO_BLOCK;
bp->b_dev = NO_DEV;
bp->b_next = bp + 1;
bp->b_prev = bp - 1;
}
buf[0].b_prev = NIL_BUF;
buf[NR_BUFS - 1].b_next = NIL_BUF;
/* Delete any buffers that span a 64K boundary, by marking them as used. */
#if (CHIP == INTEL)
for (bp = &buf[0]; bp < &buf[NR_BUFS]; bp++) {
org = get_physbase(); /* phys addr where FS is */
low_off = (vir_bytes) bp->b_data;
high_off = low_off + BLOCK_SIZE - 1;
if (((org + low_off) & M64K) != ((org + high_off) & M64K)) {
++bp->b_count; /* it was 0, by static initialization */
++bufs_in_use;
}
}
#endif
for (bp = &buf[0]; bp < &buf[NR_BUFS]; bp++) bp->b_hash = bp->b_next;
buf_hash[NO_BLOCK & (NR_BUF_HASH - 1)] = front;
}
/*===========================================================================*
* load_ram *
*===========================================================================*/
PRIVATE dev_t load_ram()
{
/* If the root device is the RAM disk, copy the entire root image device
* block-by-block to a RAM disk with the same size as the image.
* Otherwise, just allocate a RAM disk with size given in the boot parameters.
*/
register struct buf *bp, *bp1;
int count;
long k_loaded;
struct super_block *sp;
block_nr ram_offset = 0; /* block offset of RAM image on demo diskette*/
block_nr i, b;
dev_t root_device; /* really the root image device */
dev_t super_dev; /* device to get superblock from */
phys_clicks ram_clicks, init_org, init_text_clicks, init_data_clicks;
/* Get size of INIT by reading block on diskette where 'build' put it. */
init_org = data_org[INFO];
init_text_clicks = data_org[INFO + 1];
init_data_clicks = data_org[INFO + 2];
/* Print ATARI copyright message. */
#if (MACHINE == ATARI)
printf("Booting MINIX 1.5. Copyright 1990 Prentice-Hall, Inc.\n");
#endif
/* If the root device is specified in the boot parameters, use it. */
if (ROOT_DEV != DEV_RAM) {
count = boot_parameters.bp_ramsize;
super_dev = ROOT_DEV; /* get superblock directly from root device */
goto got_root_dev; /* kludge to avoid excessive indent/diffs */
} else {
super_dev = DEV_RAM; /* get superblock from RAM disk */
}
/* Get size of RAM disk by reading root